﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using GUIFramework;
using Data.GameData;
using Data.GameData.Interfaces;

namespace GUIComponents
{
    public partial class KnownRacesToolbox : DockableToolWindow
    {
        #region RaceTreeNode
        internal class RaceTreeNode : TreeNode
        {
            private Guid raceId;

            public RaceTreeNode()
            {
                raceId = Guid.Empty;
            }

            public Guid RaceId
            {
                get { return raceId; }
                set { raceId = value; }
            }
        }
        #endregion

        public KnownRacesToolbox()
        {
            InitializeComponent();
            PanelType = GamePanelType.pKNOWNRACES;
        }

        private void KnownRacesToolbox_Load(object sender, EventArgs e)
        {
            BuildRaceTree();
        }

        private void BuildRaceTree()
        {
            raceTreeView.SuspendLayout();
            raceTreeView.Nodes.Clear();

            foreach (RaceRelation race in Race.ActiveRace.KnownRaces.OrderBy(r => r.Race.Name))
            {
                RaceTreeNode node = new RaceTreeNode { RaceId = race.Race.Id, Text = race.Race.Name };
                raceTreeView.Nodes.Add(node);

                // Add other information
            }

            raceTreeView.ResumeLayout();
        }

        private void UpdateRaceTree(BasicEventArgs e)
        {
            // Determine if the active race knows about the updated race
            RaceRelation race = Race.ActiveRace.KnownRaces.FirstOrDefault(r => r.Race.Id == e.Ident);
            if (race == null)
                return;

            raceTreeView.SuspendLayout();

            if (e.Operation == BasicOperationType.eMODIFY)
            {                
                RaceTreeNode node = LocateNode(e.Ident, raceTreeView.Nodes);
                if (node != null)
                    node.Text = race.Race.Name;
            }

            if (e.Operation == BasicOperationType.eADD)
            {
                RaceTreeNode node = new RaceTreeNode { RaceId = race.Race.Id, Text = race.Race.Name };
                raceTreeView.Nodes.Add(node);
            }

            if (e.Operation == BasicOperationType.eDELETE)
            {
                RaceTreeNode node = LocateNode(e.Ident, raceTreeView.Nodes);
                node.Parent.Nodes.Remove(node);
            }

            raceTreeView.ResumeLayout();
        }

        /// <summary>
        /// Recursively search for a node containing a specific id.
        /// </summary>
        /// <param name="idToLocate">The guid id to find</param>
        /// <param name="nodes">The collection of nodes</param>
        /// <returns>The result of the search (can be null)</returns>
        private RaceTreeNode LocateNode(Guid idToLocate, TreeNodeCollection nodes)
        {
            foreach (RaceTreeNode node in nodes)
            {
                if (node.RaceId == idToLocate)
                    return node;

                RaceTreeNode childNode = LocateNode(idToLocate, node.Nodes);
                if (childNode != null)
                    return childNode;
            }

            return null;
        }

        private void negotiationsToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void propertiesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RaceTreeNode selected = raceTreeView.SelectedNode as RaceTreeNode;
            if (selected == null)
                return;

            Commands.ShowRaceProperties(Race.GetRace(selected.RaceId));
        }

        /// <summary>
        /// Select the tree node under the as the mouse is clicked.
        /// </summary>
        /// <param name="sender">Not used</param>
        /// <param name="e">The mouse arguments</param>
        private void raceTreeView_MouseDown(object sender, MouseEventArgs e)
        {
            // Change the right-click to select the node clicked on
            if (e.Button == MouseButtons.Right)
            {
                // Point where the mouse is clicked.
                Point p = new Point(e.X, e.Y);

                // Get the node that the user has clicked.
                TreeNode node = raceTreeView.GetNodeAt(p);
                if (node != null)
                    raceTreeView.SelectedNode = node;
            }
        }

        /// <summary>
        /// Update the panel from an exernal trigger
        /// </summary>
        /// <param name="e">The basic game event arguments</param>
        public override void UpdatePanel(Data.GameData.BasicEventArgs e)
        {
            if (e.EventType == BasicEventType.eRACE)
            {
                if (e.Operation == BasicOperationType.eMODIFY)
                    UpdateRaceTree(e);
                else
                    BuildRaceTree();
            }
        }
    }
}
